package com.github.houkunlin.extension;

import com.github.houkunlin.dict.GlobalDict;
import com.github.houkunlin.util.ProjectUtils;
import com.github.houkunlin.vo.impl.RootModel;
import com.intellij.database.model.DasNamespace;
import com.intellij.database.model.DasObject;
import com.intellij.database.model.DasTable;
import com.intellij.database.model.basic.BasicElement;
import com.intellij.database.model.basic.BasicModMixinElement;
import com.intellij.database.psi.DbDataSource;
import com.intellij.database.psi.DbPsiFacade;
import com.intellij.database.psi.DbTable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Conditions;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ExceptionUtil;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.JBIterable;
import lombok.Getter;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.github.houkunlin.vo.impl.RootModel.getRootModel;

/**
 * @Author tanqi
 * @Description 数据源配置
 * @Date 2022/10/12 10:29
 * @Version 1.0
 */
@Getter
public class DataSourceService {

    private static final Logger LOG = Logger.getInstance(DataSourceService.class);

    /**
     * 所有表
     */
    private Map<String, DasTable> allTables = new HashMap<>();

    private Map<String, DbTable> dbTableMap = new HashMap<>();

    DataSourceService(){
        refreshTable();
    }

    private void refreshTable() {
        // 获取当前项目所有数据源
        List<DbDataSource> dataSources = DbPsiFacade.getInstance(ProjectUtils.getCurrProject()).getDataSources();
        refreshTable(dataSources);
    }

    public synchronized void refreshTable(Collection<DbDataSource> dataSources) {
        for (DbDataSource dataSource : dataSources) {
            for (DasTable table : getTables(dataSource)) {
//                if(table.isSystem()){
//                    //跳过系统表,选择的表必须在idea插件中勾选对应的数据库
//                    continue;
//                }
                DbTable dataTable = getDataTable(table);
                dbTableMap.put(table.toString(), dataTable);
                dbTableMap.put(table.getName(), dataTable);
                BasicElement parent = ((BasicModMixinElement) table).getParent();
                if(parent != null) {
                    String dataSourceName = parent.getName();
                    this.allTables.put(dataSourceName + "." + table, table);
                    //多个数据库相同表的解决
                    dbTableMap.put(dataSourceName + "." + dataTable.getName(), dataTable);
                    dbTableMap.put(dataSourceName + "." + dataTable, dataTable);
                }
            }
        }
    }

    private JBIterable<DasTable> getTables(DbDataSource dataSource) {
        return dataSource.getModel().traverser().expandAndSkip(Conditions.instanceOf(DasNamespace.class)).filter(DasTable.class);
    }

    public static DataSourceService getInstance() {
        Application application = ApplicationManager.getApplication();
        DataSourceService dataSourceService = null;
        if(application != null) {
            dataSourceService = application.getService(DataSourceService.class);
            if(dataSourceService == null ){
                dataSourceService = new DataSourceService();
            }
        }
        return dataSourceService;
    }

    public static DbTable getDataTable(DasTable dasTable){
        if (dasTable == null) {
            return null;
        }
        DbTable dbTable = null;
        if (dasTable instanceof DbTable) {
            // 针对2017.2版本做兼容
            dbTable = (DbTable) dasTable;
        } else {
            Method method = ReflectionUtil.getMethod(DbPsiFacade.class, "findElement", DasObject.class);
            if (method == null) {
                Messages.showWarningDialog("findElement method not found", GlobalDict.TITLE_INFO);
                return dbTable;
            }
            try {
                // 针对2017.2以上版本做兼容
                dbTable = (DbTable) method.invoke(DbPsiFacade.getInstance(ProjectUtils.getCurrProject()), dasTable);
            } catch (IllegalAccessException | InvocationTargetException e1) {
                ExceptionUtil.rethrow(e1);
            }
        }
        return dbTable;
    }

    public RootModel toModel(String tableName) {
        if(StringUtil.isEmpty(tableName)){
            return null;
        }
        DbTable dbTable = dbTableMap.get(tableName);
        return getRootModel(dbTable);
    }
}
